package com.rich.dmr.server;

import java.io.DataInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintStream;
import java.io.UnsupportedEncodingException;
import java.math.BigDecimal;
import java.net.Socket;
import java.nio.charset.StandardCharsets;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import android.content.Context;
import android.os.Handler;
import android.util.Log;

import com.rich.dmr.model.ChannelModel;
import com.rich.dmr.model.Frequency;
import com.rich.dmr.utils.DataBaseUtils;
import com.rich.dmr.utils.GetPropUtils;

public class ClientHandler {
    private final String TAG = "rich---ClientHandler";
    private final Socket socket;
    private final ClientReadHandler readHandler;
    private final ClientWriteHandler writeHandler;
    private final ClientHandlerCallback clientHandlerCallback;
    private final String clientInfo;
    private Handler mHandler;
    private DataBaseUtils dataBaseUtils;

    ClientHandler(Socket socket,
                  ClientHandlerCallback clientHandlerCallback, Context context, Handler handler)
            throws IOException {
        this.socket = socket;
        this.readHandler = new ClientReadHandler(socket.getInputStream());
        this.writeHandler = new ClientWriteHandler(socket.getOutputStream());
        this.clientHandlerCallback = clientHandlerCallback;
        this.clientInfo = "A[" + socket.getInetAddress().getHostAddress()
                + "] P[" + socket.getPort() + "]";
        Log.d(TAG, "新客户端连接：" + clientInfo);
        mHandler = handler;
        dataBaseUtils = DataBaseUtils.getInstance(context);
    }

    String getClientInfo() {
        return clientInfo;
    }

    void exit() {
        readHandler.exit();
        writeHandler.exit();
        try {
            socket.close();
        } catch (IOException e) {
            e.printStackTrace();
        }

        Log.d(TAG, "客户端已退出：" + socket.getInetAddress() + " P:" + socket.getPort());
    }

    void send(String str) {
        writeHandler.send(str);
    }

    void readToPrint() {
        readHandler.start();
    }

    private void exitBySelf() {
        exit();
        clientHandlerCallback.onSelfClosed(this);
    }

    public interface ClientHandlerCallback {
        // 自身关闭通知
        void onSelfClosed(ClientHandler handler);

        // 收到消息时通知
        void onNewMessageArrived(ClientHandler handler, String msg);
    }


    class ClientReadHandler extends Thread {
        private boolean done = false;
        private final InputStream inputStream;

        ClientReadHandler(InputStream inputStream) {
            this.inputStream = inputStream;
        }

        @Override
        public void run() {
            super.run();
            try {
                // 得到输入流，用于接收数据
                DataInputStream dis = new DataInputStream(inputStream);

                do {
                    // 客户端拿到一条数据
                    // String str = socketInput.readLine();

                    byte[] bytes = new byte[1024];
                    int len;
                    StringBuilder sb = new StringBuilder();
                    try {
                        if ((len = dis.read(bytes)) != -1) {
                            sb.append(new String(bytes, 0, len, StandardCharsets.UTF_8));
                        }
                    } catch (UnsupportedEncodingException e) {
                        e.printStackTrace();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }

                    if (sb.toString().equals("") || sb.toString().length() == 0) {
                        Log.d(TAG, "客户端已无法读取数据！");
                        // 退出当前客户端
                        mHandler.sendEmptyMessage(5);
                        ClientHandler.this.exitBySelf();
                        break;
                    }
                    messageSwitch(sb.toString());
                    // 通知到TCPServer
                    // clientHandlerCallback.onNewMessageArrived(ClientHandler.this,sb.toString());
                } while (!done);
            } catch (Exception e) {
                if (!done) {
                    Log.d(TAG, "连接异常断开！");
                    ClientHandler.this.exitBySelf();
                }
            } finally {
                // 连接关闭
                try {
                    inputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

        private boolean isDelete = false;

        private void messageSwitch(String msg) {
            if ("1000".equals(msg)) {
                mHandler.removeMessages(0);
                mHandler.sendEmptyMessageDelayed(0, 4000);
                writeHandler.send("102");
            } else if (msg.contains("Fre:")) {

                if(!isDelete){
                   // dataBaseUtils.deleteFrequency();
                    isDelete = true;
                   // mHandler.sendEmptyMessageDelayed(1, 100);
                }

                String[] msgs = msg.split("/");
                String channel = msgs[1];
                String txFreq = msgs[2];
                String rxFreq = msgs[3];
                if (channel.length() > 0 && txFreq.length() > 0 && rxFreq.length() > 0) {
                    int txFrequency = (int) mul(Double.parseDouble(txFreq), 1000000);
                    int rxFrequency = (int) mul(Double.parseDouble(rxFreq), 1000000);
                    Log.d(TAG, "channel=" + channel + "txFrequency=" + txFrequency);
                    if (txFrequency >= 400000000 && txFrequency <= 480000000 && rxFrequency >= 400000000 && rxFrequency <= 480000000) {
                        if ((txFrequency % 12500) == 0 && (rxFrequency % 12500) == 0) {
                            if (dataBaseUtils.findChannel(txFrequency,rxFrequency) > 0) {
                                if (dataBaseUtils.insertChannel(channel,txFrequency,rxFrequency)) {
                                    writeHandler.send("channel:" + channel + "  success");
                                    mHandler.sendEmptyMessageDelayed(1, 500);
                                    Log.d(TAG, "channel insert success..");
                                } else {
                                    writeHandler.send("channel:" + channel + " fail");
                                    Log.d(TAG, "channel insert fail..");
                                }
                            } else {
                                writeHandler.send("channel:" + channel + " exist");
                                Log.d(TAG, "channel exist..");
                            }
                        } else {
                            writeHandler.send("channel:" + channel + " data illegal.");
                            Log.d(TAG, "channel illegal..");
                        }
                    } else {
                        writeHandler.send("channel:" + channel + " out of range.");
                        Log.d(TAG, "channel out of range..");
                    }
                } else {
                    writeHandler.send("channel:" + channel + " no channel.");
                    Log.d(TAG, "no channel..");
                }
            } else if (msg.contains("color") && msg.contains("group")) {
                String[] msgs = msg.split("&");
                String color = msgs[0].split(":")[1];
                mHandler.obtainMessage(3, 0, Integer.valueOf(color)).sendToTarget();
                Log.d(TAG, "color=" + color);
                if (msgs[1].length() > 6) {
                    String group = msgs[1].split(":")[1];
                    if (group.length() <= 8) {
                        mHandler.obtainMessage(4, 0, Integer.valueOf(group)).sendToTarget();
                    }
                    Log.d(TAG, "group=" + group);
                }
                writeHandler.send("color:success");
            } else if (msg.contains("pc Connected")) {
                writeHandler.send("DP:" + GetPropUtils.getProp("ro.product.model"));
                try {
                    sleep(500);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                writeHandler.send("DV:" + GetPropUtils.getProp("ro.custom.version"));
            } else if (msg.equals("10000")) {
                Log.d(TAG, "start read");
                final List<ChannelModel> mList = dataBaseUtils.findChannelList();
                if (mList == null) {
                    writeHandler.send("Frequency read:null");
                } else {
                    writeHandler.send("readStart");
                    for (ChannelModel fre : mList) {
                        try {
                            sleep(300);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                        writeHandler.send(fre.toString());
                    }
                    try {
                        sleep(300);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    writeHandler.send("readEnd");
                }
            }
        }


        double mul(double v1, double v2) {
            BigDecimal b1 = new BigDecimal(Double.toString(v1));
            BigDecimal b2 = new BigDecimal(Double.toString(v2));
            return b1.multiply(b2).doubleValue();
        }

        void exit() {
            done = true;
            try {
                inputStream.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    class ClientWriteHandler {
        private boolean done = false;
        private final PrintStream printStream;
        private final ExecutorService executorService;

        ClientWriteHandler(OutputStream outputStream) {
            this.printStream = new PrintStream(outputStream);
            this.executorService = Executors.newSingleThreadExecutor();
        }

        void exit() {
            done = true;
            printStream.close();
            executorService.shutdownNow();
        }

        void send(String str) {
            executorService.execute(new WriteRunnable(str));
        }

        class WriteRunnable implements Runnable {
            private final String msg;

            WriteRunnable(String msg) {
                this.msg = msg;
            }

            @Override
            public void run() {
                if (ClientWriteHandler.this.done) {
                    return;
                }

                try {
                    ClientWriteHandler.this.printStream.println(msg);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    }
}
